﻿/**
 * Copyright (C) 2012-2013 original author and authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;

namespace NGuice.Test
{
    public static class Asserts
    {
        /// <summary>
        /// 只有当expected和actual互相相等且哈希码相同时，才相等。对测试equals方法自身非常有用
        /// </summary>
        /// <param name="expected"></param>
        /// <param name="actual"></param>
        public static void AssertEqualsBothWays(object expected, object actual)
        {
            Assert.IsNotNull(expected);
            Assert.IsNotNull(actual);
            Assert.IsTrue(expected.Equals(actual), "expected.equals(actual)");
            Assert.IsTrue(actual.Equals(expected), "actual.equals(expected)");
            Assert.AreEqual(expected.GetHashCode(), actual.GetHashCode(), "HashCode");
        }

        /// <summary>
        /// 除非text按照顺序包含所有子串，否则将断言失败
        /// </summary>
        /// <param name="text"></param>
        /// <param name="?"></param>
        public static void AssertContains(string text, params string[] substrings)
        {
            /*if[NO_AOP]
            // when we strip out bytecode manipulation, we lose the ability to generate some source lines.
            if (text.contains("(Unknown Source)")) {
              return;
            }
            end[NO_AOP]*/

            int startingFrom = 0;
            foreach (string substring in substrings)
            {
                int index = text.IndexOf(substring, startingFrom);
                Assert.IsTrue(index >= startingFrom, string.Format("Expected \"{0}\" to contain substring \"{1}\"", text, substring));
                startingFrom = index + substring.Length;
            }

            string lastSubstring = substrings[substrings.Length - 1];
            Assert.IsTrue(text.IndexOf(lastSubstring, startingFrom) == -1, string.Format("Expected \"{0}\" to contain substring \"{1}\" only once),",
                text, lastSubstring));
        }

        /// <summary>
        /// 当反序列化时，如果对象等于自身则断言成功，否则失败
        /// </summary>
        /// <param name="obj"></param>
        public static void AssertEqualWhenReserialized(object obj)
        {
            object reserialized = Reserialize(obj);
            Assert.AreEqual(obj, reserialized);
            Assert.AreEqual(obj.GetHashCode(), reserialized.GetHashCode());
        }

        /// <summary>
        ///  当反序列化时，除非ToString相同，否则断言失败
        /// </summary>
        /// <param name="obj"></param>
        public static void AssertSimilarWhenReserialized(object obj)
        {
            object reserialized = Reserialize(obj);
            Assert.AreEqual(obj.ToString(), reserialized.ToString());
        }

        /// <summary>
        /// </summary>
        /// <param name="original"></param>
        /// <returns></returns>
        /// <exception cref="SerializationException">序列化异常</exception>
        public static object Reserialize(object original)
        {
                MemoryStream outStream = new MemoryStream();
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(outStream, original);
                return bf.Deserialize(outStream);
        }

        public static void AssertNotSerializable(object obj)
        {
            try
            {
                Reserialize(obj);
                Assert.Fail();
            }
            catch (Exception expected)
            {
            }
        }
    }
}
